from django.db import models
from django.contrib.auth.models import AbstractUser
from itsdangerous import TimedJSONWebSignatureSerializer as TJSSerializer, BadData
from django.conf import settings

from meiduo_mall.utils.models import BaseModel
from . import constants
# Create your models here.


# 继承系统已经创建好的模型类(不过里面的字段不一定都需要,还有不一定都有,没有的需要自己创建)
class User(AbstractUser):
    """用户模型类"""
    # 添加继承类中不存在的手机号字段
                     # 字符串    最大长度        唯一性            管理界面显示
    mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')

    # 创建邮箱激活状态字段
    email_active = models.BooleanField(default=False, verbose_name="邮箱激活状态")
    # 补充默认邮箱字段
    default_address = models.ForeignKey('Address', related_name='users', null=True, blank=True,
                                        on_delete=models.SET_NULL, verbose_name='默认地址')

    class Meta:
        """元类--> 主要作用配置信息"""
        db_table = "tb_users"  # 定义数据库名
        verbose_name = '用户'
        verbose_name_plural = verbose_name



    def generate_email_verify_url(self):
        """生成加密激活url进行序列化"""

        # 1.创建加密的序列化器对象         SECRET_KEY                过期时间
        serializer = TJSSerializer(settings.SECRET_KEY, constants.VERIFY_EMAIL_TOKEN_EXPIRES)

        # 2.构造要加密的数据
        data = {'user_id': self.id, 'email': self.email}
        # 3.加密并解码 生成 token
        token = serializer.dumps(data).decode()
        # return   '前面固定的' + 'token=' + xxxx
        verify_url = 'http://www.meiduo.site:8080/success_verify_email.html?token=' + token
        # 返回 激活邮箱url
        return verify_url

    # 静态方法生成解密
    @staticmethod
    def check_email_verify_url(token):
        """解密并获取user对象"""
        # 1.创建解密的序列化器对象
        serializer = TJSSerializer(settings.SECRET_KEY, constants.VERIFY_EMAIL_TOKEN_EXPIRES)
        # 解密
        try:
            data = serializer.loads(token)
        except BadData:
            return None
        else:
            # 解密成功 获得 user_id和email的字典, 一一取出
            user_id = data.get('user_id')
            email = data.get('email')
            try:
                # 联合查询 获得 user对象
                user = User.objects.get(id=user_id, email=email)
            except User.DoesNotExist:
                # 不存在返回None
                return None
            else:
                # 存在返回user对象
                return user


# 注意点: 要放在User后面  因为字段中用到User
class Address(BaseModel):
    """ 用户地址 """
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='addresses', verbose_name='用户')
    title = models.CharField(max_length=20, verbose_name='地址名称')
    receiver = models.CharField(max_length=20, verbose_name='收货人')
    #                   外键       动态关联模型, 只要不在该类的py文件上面 就要加上双引号
    """源码中to._meta.model_name 会去序列化器中找元类对应的模型 并且是要字符串"""
    province = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='province_addresses', verbose_name='省')
    #                          跨App 关联 ==> (只要 App名.模型名 即可) 中间会自动补上models
    city = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='city_addresses', verbose_name='市')
    district = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='district_addresses', verbose_name='区')
    place = models.CharField(max_length=50, verbose_name='地址')
    mobile = models.CharField(max_length=11, verbose_name='手机')
    tel = models.CharField(max_length=20, null=True, blank=True, default='', verbose_name='固定电话')
    email = models.CharField(max_length=30, null=True, blank=True, default='', verbose_name='电子邮箱')
    is_deleted = models.BooleanField(default=False, verbose_name='逻辑删除')

    # 元类
    class Meta:
        # 表名
        db_table = 'tb_address'
        verbose_name = '用户地址'
        verbose_name_plural = verbose_name
        # 定义排序   更新时间降序 排序
        ordering = ['-update_time']  # TODO:待扩展


